<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>影刀执行记录更新接口测试</title>
  <!-- 引入Vue.js -->
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <!-- 引入ElementPlus -->
  <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
  <script src="https://unpkg.com/element-plus"></script>
  <!-- 引入axios -->
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <style>
    body {
      font-family: "PingFang SC", "Helvetica Neue", Arial, sans-serif;
      margin: 0;
      padding: 20px;
      background-color: #f5f7fa;
    }
    .container {
      max-width: 1000px;
      margin: 0 auto;
      background-color: #fff;
      padding: 20px;
      border-radius: 4px;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    }
    .header {
      border-bottom: 1px solid #ebeef5;
      padding-bottom: 15px;
      margin-bottom: 20px;
    }
    .log-container {
      background-color: #1e1e1e;
      color: #c0c0c0;
      padding: 10px;
      border-radius: 4px;
      height: 300px;
      overflow-y: auto;
      margin-top: 20px;
      font-family: monospace;
    }
    .log-entry {
      margin: 5px 0;
      white-space: pre-wrap;
      word-break: break-all;
    }
    .success {
      color: #67c23a;
    }
    .error {
      color: #f56c6c;
    }
    .info {
      color: #409eff;
    }
    .warning {
      color: #e6a23c;
    }
    .card-title {
      font-size: 16px;
      margin-bottom: 15px;
    }
    .step-container {
      margin-bottom: 15px;
    }
    .json-viewer {
      background-color: #f5f7fa;
      border: 1px solid #e4e7ed;
      border-radius: 4px;
      padding: 10px;
      max-height: 200px;
      overflow-y: auto;
      margin-top: 10px;
      font-family: monospace;
      white-space: pre-wrap;
    }
  </style>
</head>
<body>
  <div id="app" class="container">
    <div class="header">
      <h2>影刀执行记录更新接口测试</h2>
      <p>此页面用于测试影刀执行记录更新API接口</p>
    </div>

    <el-form :model="config" label-width="120px" size="default">
      <el-form-item label="API基础URL">
        <el-input v-model="config.baseUrl" placeholder="例如: http://localhost:8000"></el-input>
      </el-form-item>
      
      <el-form-item label="用户名">
        <el-input v-model="config.username" placeholder="请输入用户名"></el-input>
      </el-form-item>
      
      <el-form-item label="密码">
        <el-input v-model="config.password" type="password" placeholder="请输入密码"></el-input>
      </el-form-item>
    </el-form>

    <!-- 测试步骤 -->
    <el-card class="step-container">
      <template #header>
        <div class="card-title">测试流程</div>
      </template>
      
      <el-steps :active="currentStep" finish-status="success" simple>
        <el-step title="登录"></el-step>
        <el-step title="创建流程"></el-step>
        <el-step title="运行流程"></el-step>
        <el-step title="状态更新为运行中"></el-step>
        <el-step title="状态更新为已完成"></el-step>
        <el-step title="清理测试数据"></el-step>
      </el-steps>
      
      <div style="margin-top: 20px; display: flex; justify-content: space-between;">
        <el-button type="primary" @click="runTest" :disabled="isRunning">开始测试</el-button>
        <el-button type="danger" @click="cleanupAll" :disabled="!canCleanup">清理所有测试数据</el-button>
      </div>
    </el-card>

    <!-- 当前测试状态 -->
    <el-card v-if="testState.processId || testState.executionId">
      <template #header>
        <div class="card-title">当前测试状态</div>
      </template>
      
      <el-descriptions :column="2" border>
        <el-descriptions-item label="流程ID" v-if="testState.processId">{{ testState.processId }}</el-descriptions-item>
        <el-descriptions-item label="执行记录ID" v-if="testState.executionId">{{ testState.executionId }}</el-descriptions-item>
        <el-descriptions-item label="当前状态" v-if="testState.status">{{ testState.status }}</el-descriptions-item>
      </el-descriptions>
      
      <template v-if="testState.responseData">
        <div style="margin-top: 15px; font-weight: bold;">最近响应数据:</div>
        <div class="json-viewer">{{ formatJson(testState.responseData) }}</div>
      </template>
    </el-card>

    <!-- 执行日志 -->
    <div class="log-container">
      <div v-for="(log, index) in logs" :key="index" :class="`log-entry ${log.type}`">
        [{{ log.time }}] {{ log.message }}
      </div>
    </div>
  </div>

  <script>
    const { createApp, ref, reactive, computed, nextTick } = Vue
    
    createApp({
      setup() {
        // 配置信息
        const config = reactive({
          baseUrl: 'http://localhost:8000',
          username: 'admin',
          password: 'admin123'
        })
        
        // 测试状态
        const testState = reactive({
          token: null,
          processId: null,
          executionId: null,
          status: null,
          responseData: null
        })
        
        // 日志记录
        const logs = ref([])
        
        // 当前测试步骤
        const currentStep = ref(0)
        
        // 测试是否正在运行
        const isRunning = ref(false)
        
        // 是否可以清理
        const canCleanup = computed(() => {
          return testState.processId || testState.executionId
        })
        
        // 添加日志
        const addLog = (message, type = 'info') => {
          const now = new Date()
          const timeStr = now.toLocaleTimeString('zh-CN', { 
            hour: '2-digit', 
            minute: '2-digit', 
            second: '2-digit',
            hour12: false
          })
          
          logs.value.push({
            time: timeStr,
            message,
            type
          })
          
          // 滚动日志到底部
          nextTick(() => {
            const logContainer = document.querySelector('.log-container')
            if (logContainer) {
              logContainer.scrollTop = logContainer.scrollHeight
            }
          })
        }
        
        // 设置headers
        const getHeaders = () => {
          return {
            'Content-Type': 'application/json',
            'Authorization': testState.token ? `Bearer ${testState.token}` : ''
          }
        }
        
        // 格式化JSON输出
        const formatJson = (data) => {
          try {
            return JSON.stringify(data, null, 2)
          } catch (e) {
            return data
          }
        }
        
        // 登录
        const login = async () => {
          try {
            addLog('开始登录...')
            
            const loginData = new FormData()
            loginData.append('username', config.username)
            loginData.append('password', config.password)
            
            const response = await axios.post(
              `${config.baseUrl}/api/token`, 
              loginData,
              { headers: { 'Content-Type': 'multipart/form-data' } }
            )
            
            testState.token = response.data.access_token
            addLog(`登录成功，获取到token: ${testState.token.substring(0, 10)}...`, 'success')
            return true
          } catch (error) {
            addLog(`登录失败: ${error.response?.data?.detail || error.message}`, 'error')
            return false
          }
        }
        
        // 创建流程
        const createProcess = async () => {
          try {
            addLog('创建测试流程...')
            
            const processData = {
              name: `测试流程_${new Date().getTime()}`,
              description: "这是一个用于测试的影刀流程",
              process_define_id: "test_process_001",
              parameters: {
                target_url: "https://example.com",
                data_fields: ["title", "price", "description"]
              },
              output_file_path: "D:/影刀RPA/测试/test_output.json"
            }
            
            const response = await axios.post(
              `${config.baseUrl}/api/wingknife/processes`,
              processData,
              { headers: getHeaders() }
            )
            
            testState.processId = response.data.id
            testState.responseData = response.data
            addLog(`创建流程成功，流程ID: ${testState.processId}`, 'success')
            return true
          } catch (error) {
            addLog(`创建流程失败: ${error.response?.data?.detail || error.message}`, 'error')
            return false
          }
        }
        
        // 运行流程
        const runProcess = async () => {
          try {
            addLog(`运行流程，ID: ${testState.processId}...`)
            
            const runData = {
              params: {
                test_param: "test_value",
                run_time: new Date().toISOString()
              }
            }
            
            const response = await axios.post(
              `${config.baseUrl}/api/wingknife/processes/${testState.processId}/run`,
              runData,
              { headers: getHeaders() }
            )
            
            testState.executionId = response.data.id
            testState.status = response.data.status
            testState.responseData = response.data
            addLog(`运行流程成功，执行ID: ${testState.executionId}`, 'success')
            return true
          } catch (error) {
            addLog(`运行流程失败: ${error.response?.data?.detail || error.message}`, 'error')
            return false
          }
        }
        
        // 更新执行状态为运行中
        const updateToRunning = async () => {
          try {
            addLog(`更新执行状态为"运行中"，执行ID: ${testState.executionId}...`)
            
            const updateData = {
              status: "running",
              started_at: new Date().toISOString()
            }
            
            const response = await axios.put(
              `${config.baseUrl}/api/wingknife/executions/${testState.executionId}`,
              updateData,
              { headers: getHeaders() }
            )
            
            testState.status = response.data.status
            testState.responseData = response.data
            addLog(`更新状态成功，当前状态: ${testState.status}`, 'success')
            return true
          } catch (error) {
            addLog(`更新状态失败: ${error.response?.data?.detail || error.message}`, 'error')
            return false
          }
        }
        
        // 更新执行状态为已完成
        const updateToCompleted = async () => {
          try {
            addLog(`更新执行状态为"已完成"，执行ID: ${testState.executionId}...`)
            
            const updateData = {
              status: "completed",
              completed_at: new Date().toISOString(),
              result: {
                records_processed: 100,
                success_count: 95,
                failure_count: 5,
                processed_time: "00:05:30",
                summary: "处理完成，共处理100条记录"
              }
            }
            
            const response = await axios.put(
              `${config.baseUrl}/api/wingknife/executions/${testState.executionId}`,
              updateData,
              { headers: getHeaders() }
            )
            
            testState.status = response.data.status
            testState.responseData = response.data
            addLog(`更新状态成功，当前状态: ${testState.status}`, 'success')
            return true
          } catch (error) {
            addLog(`更新状态失败: ${error.response?.data?.detail || error.message}`, 'error')
            return false
          }
        }
        
        // 清理测试数据
        const cleanup = async () => {
          try {
            addLog('开始清理测试数据...')
            
            if (testState.executionId) {
              await axios.delete(
                `${config.baseUrl}/api/wingknife/executions/${testState.executionId}`,
                { headers: getHeaders() }
              )
              addLog(`删除执行记录成功，ID: ${testState.executionId}`, 'success')
            }
            
            if (testState.processId) {
              await axios.delete(
                `${config.baseUrl}/api/wingknife/processes/${testState.processId}`,
                { headers: getHeaders() }
              )
              addLog(`删除流程成功，ID: ${testState.processId}`, 'success')
            }
            
            // 重置测试状态
            testState.processId = null
            testState.executionId = null
            testState.status = null
            testState.responseData = null
            
            return true
          } catch (error) {
            addLog(`清理测试数据失败: ${error.response?.data?.detail || error.message}`, 'error')
            return false
          }
        }
        
        // 运行测试
        const runTest = async () => {
          isRunning.value = true
          currentStep.value = 0
          
          try {
            addLog('=== 开始测试影刀执行记录更新功能 ===', 'info')
            
            // 1. 登录
            if (await login()) {
              currentStep.value = 1
            } else {
              throw new Error('登录失败，测试终止')
            }
            
            // 等待1秒
            await new Promise(resolve => setTimeout(resolve, 1000))
            
            // 2. 创建流程
            if (await createProcess()) {
              currentStep.value = 2
            } else {
              throw new Error('创建流程失败，测试终止')
            }
            
            // 等待1秒
            await new Promise(resolve => setTimeout(resolve, 1000))
            
            // 3. 运行流程
            if (await runProcess()) {
              currentStep.value = 3
            } else {
              throw new Error('运行流程失败，测试终止')
            }
            
            // 等待2秒，模拟流程开始执行
            addLog('等待2秒...')
            await new Promise(resolve => setTimeout(resolve, 2000))
            
            // 4. 更新状态为运行中
            if (await updateToRunning()) {
              currentStep.value = 4
            } else {
              throw new Error('更新状态为运行中失败，测试终止')
            }
            
            // 等待3秒，模拟流程执行过程
            addLog('等待3秒...')
            await new Promise(resolve => setTimeout(resolve, 3000))
            
            // 5. 更新状态为已完成
            if (await updateToCompleted()) {
              currentStep.value = 5
            } else {
              throw new Error('更新状态为已完成失败，测试终止')
            }
            
            // 等待1秒
            await new Promise(resolve => setTimeout(resolve, 1000))
            
            // 6. 清理测试数据
            addLog('测试完成，是否清理测试数据？', 'warning')
            
            addLog('=== 测试完成 ===', 'success')
          } catch (error) {
            addLog(`测试过程出错: ${error.message}`, 'error')
          } finally {
            isRunning.value = false
          }
        }
        
        // 清理所有测试数据
        const cleanupAll = async () => {
          if (await cleanup()) {
            currentStep.value = 0
            addLog('所有测试数据已清理完毕', 'success')
          }
        }
        
        return {
          config,
          testState,
          logs,
          currentStep,
          isRunning,
          canCleanup,
          runTest,
          cleanupAll,
          formatJson
        }
      }
    }).use(ElementPlus).mount('#app')
  </script>
</body>
</html> 